<!DOCTYPE html>
<html lang="en-us">
  <head>

    <meta http-equiv="content-type" content="text/html; charset=utf-8">
    
<meta charset="UTF-8">
<title>All About Caching | Elasticsearch: The Definitive Guide [2.x] | Elastic</title>
<link rel="home" href="index.html" title="Elasticsearch: The Definitive Guide [2.x]">
<link rel="up" href="structured-search.html" title="Structured Search">
<link rel="prev" href="_dealing_with_null_values.html" title="Dealing with Null Values">
<link rel="next" href="full-text-search.html" title="Full-Text Search">
<meta name="DC.type" content="Learn/Docs/Legacy/Elasticsearch/Definitive Guide/2.x">
<meta name="DC.subject" content="Elasticsearch">
<meta name="DC.identifier" content="2.x">
<meta name="robots" content="noindex,nofollow">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <script src="https://cdn.optimizely.com/js/18132920325.js"></script>
    <link rel="apple-touch-icon" sizes="57x57" href="/apple-icon-57x57.png">
    <link rel="apple-touch-icon" sizes="60x60" href="/apple-icon-60x60.png">
    <link rel="apple-touch-icon" sizes="72x72" href="/apple-icon-72x72.png">
    <link rel="apple-touch-icon" sizes="76x76" href="/apple-icon-76x76.png">
    <link rel="apple-touch-icon" sizes="114x114" href="/apple-icon-114x114.png">
    <link rel="apple-touch-icon" sizes="120x120" href="/apple-icon-120x120.png">
    <link rel="apple-touch-icon" sizes="144x144" href="/apple-icon-144x144.png">
    <link rel="apple-touch-icon" sizes="152x152" href="/apple-icon-152x152.png">
    <link rel="apple-touch-icon" sizes="180x180" href="/apple-icon-180x180.png">
    <link rel="icon" type="image/png" href="/favicon-32x32.png" sizes="32x32">
    <link rel="icon" type="image/png" href="/android-chrome-192x192.png" sizes="192x192">
    <link rel="icon" type="image/png" href="/favicon-96x96.png" sizes="96x96">
    <link rel="icon" type="image/png" href="/favicon-16x16.png" sizes="16x16">
    <link rel="manifest" href="/manifest.json">
    <meta name="apple-mobile-web-app-title" content="Elastic">
    <meta name="application-name" content="Elastic">
    <meta name="msapplication-TileColor" content="#ffffff">
    <meta name="msapplication-TileImage" content="/mstile-144x144.png">
    <meta name="theme-color" content="#ffffff">
    <meta name="naver-site-verification" content="936882c1853b701b3cef3721758d80535413dbfd">
    <meta name="yandex-verification" content="d8a47e95d0972434">
    <meta name="localized" content="true">
    <meta name="st:robots" content="follow,index">
    <meta property="og:image" content="https://www.elastic.co/static/images/elastic-logo-200.png">
    <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">
    <link rel="icon" href="/favicon.ico" type="image/x-icon">
    <link rel="apple-touch-icon-precomposed" sizes="64x64" href="/favicon_64x64_16bit.png">
    <link rel="apple-touch-icon-precomposed" sizes="32x32" href="/favicon_32x32.png">
    <link rel="apple-touch-icon-precomposed" sizes="16x16" href="/favicon_16x16.png">
    <!-- Give IE8 a fighting chance -->
    <!--[if lt IE 9]>
    <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
    <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
    <![endif]-->
    <link rel="stylesheet" type="text/css" href="/guide/static/styles.css">
  </head>

  <!--© 2015-2021 Elasticsearch B.V. Copying, publishing and/or distributing without written permission is strictly prohibited.-->

  <body>
    <!-- Google Tag Manager -->
    <script>dataLayer = [];</script><noscript><iframe src="//www.googletagmanager.com/ns.html?id=GTM-58RLH5" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
    <script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= '//www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); })(window,document,'script','dataLayer','GTM-58RLH5');</script>
    <!-- End Google Tag Manager -->

    <!-- Global site tag (gtag.js) - Google Analytics -->
    <script async src="https://www.googletagmanager.com/gtag/js?id=UA-12395217-16"></script>
    <script>
      window.dataLayer = window.dataLayer || [];
      function gtag(){dataLayer.push(arguments);}
      gtag('js', new Date());
      gtag('config', 'UA-12395217-16');
    </script>

    <!--BEGIN QUALTRICS WEBSITE FEEDBACK SNIPPET-->
    <script type="text/javascript">
      (function(){var g=function(e,h,f,g){
      this.get=function(a){for(var a=a+"=",c=document.cookie.split(";"),b=0,e=c.length;b<e;b++){for(var d=c[b];" "==d.charAt(0);)d=d.substring(1,d.length);if(0==d.indexOf(a))return d.substring(a.length,d.length)}return null};
      this.set=function(a,c){var b="",b=new Date;b.setTime(b.getTime()+6048E5);b="; expires="+b.toGMTString();document.cookie=a+"="+c+b+"; path=/; "};
      this.check=function(){var a=this.get(f);if(a)a=a.split(":");else if(100!=e)"v"==h&&(e=Math.random()>=e/100?0:100),a=[h,e,0],this.set(f,a.join(":"));else return!0;var c=a[1];if(100==c)return!0;switch(a[0]){case "v":return!1;case "r":return c=a[2]%Math.floor(100/c),a[2]++,this.set(f,a.join(":")),!c}return!0};
      this.go=function(){if(this.check()){var a=document.createElement("script");a.type="text/javascript";a.src=g;document.body&&document.body.appendChild(a)}};
      this.start=function(){var a=this;window.addEventListener?window.addEventListener("load",function(){a.go()},!1):window.attachEvent&&window.attachEvent("onload",function(){a.go()})}};
      try{(new g(100,"r","QSI_S_ZN_emkP0oSe9Qrn7kF","https://znemkp0ose9qrn7kf-elastic.siteintercept.qualtrics.com/WRSiteInterceptEngine/?Q_ZID=ZN_emkP0oSe9Qrn7kF")).start()}catch(i){}})();
    </script><div id="ZN_emkP0oSe9Qrn7kF"><!--DO NOT REMOVE-CONTENTS PLACED HERE--></div>
    <!--END WEBSITE FEEDBACK SNIPPET-->

    <div id="elastic-nav" style="display:none;"></div>
    <script src="https://www.elastic.co/elastic-nav.js"></script>

    <!-- Subnav -->
    <div>
      <div>
        <div class="tertiary-nav d-none d-md-block">
          <div class="container">
            <div class="p-t-b-15 d-flex justify-content-between nav-container">
              <div class="breadcrum-wrapper"><span><a href="/guide/" style="font-size: 14px; font-weight: 600; color: #000;">Docs</a></span></div>
            </div>
          </div>
        </div>
      </div>
    </div>

    <div class="main-container">
      <section id="content">
        <div class="content-wrapper">

          <section id="guide" lang="en">
            <div class="container">
              <div class="row">
                <div class="col-xs-12 col-sm-8 col-md-8 guide-section">
                  <!-- start body -->
                  <div class="page_header">
<p>
  <strong>WARNING</strong>: The 2.x versions of Elasticsearch have passed their
  <a href="https://www.elastic.co/support/eol">EOL dates</a>. If you are running
  a 2.x version, we strongly advise you to upgrade.
</p>
<p>
  This documentation is no longer maintained and may be removed. For the latest
  information, see the <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html">current
  Elasticsearch documentation</a>.
</p>
</div>
<div id="content">
<div class="breadcrumbs">
<span class="breadcrumb-link"><a href="index.html">Elasticsearch: The Definitive Guide [2.x]</a></span>
»
<span class="breadcrumb-link"><a href="search-in-depth.html">Search in Depth</a></span>
»
<span class="breadcrumb-link"><a href="structured-search.html">Structured Search</a></span>
»
<span class="breadcrumb-node">All About Caching</span>
</div>
<div class="navheader">
<span class="prev">
<a href="_dealing_with_null_values.html">« Dealing with Null Values</a>
</span>
<span class="next">
<a href="full-text-search.html">Full-Text Search »</a>
</span>
</div>
<div class="section">
<div class="titlepage"><div><div>
<h2 class="title">
<a id="filter-caching"></a>All About Caching<a class="edit_me edit_me_private" rel="nofollow" title="Editing on GitHub is available to Elastic" href="https://github.com/elastic/elasticsearch-definitive-guide/edit/2.x/080_Structured_Search/40_bitsets.asciidoc">edit</a>
</h2>
</div></div></div>
<p>Earlier in this chapter (<a class="xref" href="_finding_exact_values.html#_internal_filter_operation" title="Internal Filter Operation">Internal Filter Operation</a>), we briefly discussed
how non-scoring queries are calculated.

  At their
heart is a bitset representing which documents match the filter.  When Elasticsearch
determines a bitset is likely to be reused in the future, it will be cached directly
in memory for later use.  Once cached, these bitsets can be reused <em>wherever</em>
the same query is used, without having to reevaluate the entire query again.</p>
<p>These cached bitsets are “smart”: they are updated incrementally. As you
index new documents, only those new documents need to be added to the existing
bitsets, rather than having to recompute the entire cached filter over and
over. Filters are real-time like the rest of the system; you don’t need to
worry about cache expiry.</p>
<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="_independent_query_caching"></a>Independent Query Caching<a class="edit_me edit_me_private" rel="nofollow" title="Editing on GitHub is available to Elastic" href="https://github.com/elastic/elasticsearch-definitive-guide/edit/2.x/080_Structured_Search/40_bitsets.asciidoc">edit</a>
</h3>
</div></div></div>
<p>The bitsets belonging to a query component are independent from the rest of the
search request.  This means that, once cached, a query can be reused in multiple
search requests.  It is not dependent on the "context" of the surrounding query.
This allows caching to accelerate the most frequently used portions of your queries,
without wasting overhead on the less frequent / more volatile portions.</p>
<p>Similarly, if a single search request reuses the same non-scoring query, its
cached bitset can be reused for all instances inside the single search request.</p>
<p>Let’s look at this example query, which looks for emails that are either of the following:</p>
<div class="ulist itemizedlist">
<ul class="itemizedlist">
<li class="listitem">
In the inbox and have not been read
</li>
<li class="listitem">
<em>Not</em> in the inbox but have been marked as important
</li>
</ul>
</div>
<div class="pre_wrapper lang-js">
<pre class="programlisting prettyprint lang-js">GET /inbox/emails/_search
{
  "query": {
      "constant_score": {
          "filter": {
              "bool": {
                 "should": [
                    { "bool": {
                          "must": [
                             { "term": { "folder": "inbox" }}, <a id="CO55-1"></a><i class="conum" data-value="1"></i>
                             { "term": { "read": false }}
                          ]
                    }},
                    { "bool": {
                          "must_not": {
                             "term": { "folder": "inbox" } <a id="CO55-2"></a><i class="conum" data-value="1"></i>
                          },
                          "must": {
                             "term": { "important": true }
                          }
                    }}
                 ]
              }
            }
        }
    }
}</pre>
</div>
<div class="calloutlist">
<table border="0" summary="Callout list">
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO55-1"><i class="conum" data-value="1"></i></a><a href="#CO55-2"></a></p>
</td>
<td align="left" valign="top">
<p>These two queries are identical and will use the same bitset.</p>
</td>
</tr>
</table>
</div>
<p>Even though one of the inbox clauses is a <code class="literal">must</code> clause and the other is a
<code class="literal">must_not</code> clause, the two clauses themselves are identical. If this particular
<code class="literal">term</code> query was previously cached, both instances would benefit from the cached
representation despite being used in different styles of boolean logic.</p>
<p>This ties in nicely with the composability of the query DSL.  It is easy to
move filtering queries around, or reuse the same query in multiple places within the
search request.  This isn’t just convenient to the developer—​it has direct
performance benefits.</p>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="_autocaching_behavior"></a>Autocaching Behavior<a class="edit_me edit_me_private" rel="nofollow" title="Editing on GitHub is available to Elastic" href="https://github.com/elastic/elasticsearch-definitive-guide/edit/2.x/080_Structured_Search/40_bitsets.asciidoc">edit</a>
</h3>
</div></div></div>
<p>In older versions of Elasticsearch, the default behavior was to cache everything
that was cacheable.  This often meant the system cached bitsets too aggressively
and performance suffered due to thrashing the cache.  In addition, many filters
are very fast to evaluate, but substantially slower to cache (and reuse from cache).
These filters don’t make sense to cache, since you’d be better off just re-executing
the filter again.</p>
<p>Inspecting the inverted index is very fast and most query components are rare.
Consider a <code class="literal">term</code> filter on a <code class="literal">"user_id"</code> field:  if you have millions of users,
any particular user ID will only occur rarely.  It isn’t profitable to cache
the bitsets for this filter, as the cached result will likely be evicted
from the cache before it is used again.</p>
<p>This type of cache churn can have serious effects on performance.  What’s worse,
it is difficult for developers to identify which components exhibit good cache
behavior and which are useless.</p>
<p>To address this, Elasticsearch caches queries automatically based on usage frequency.
If a non-scoring query has been used a few times (dependent on the query type) in the last 256 queries,
the query is a candidate for caching.  However, not all segments are guaranteed
to cache the bitset.  Only segments that hold more than 10,000 documents (or 3%
of the total documents, whichever is larger) will cache the bitset.  Because
small segments are fast to search and merged out quickly, it doesn’t make sense
to cache bitsets here.</p>
<p>Once cached, a non-scoring bitset will remain in the cache until it is evicted.
Eviction is done on an LRU basis: the least-recently used filter will be evicted
once the cache is full.</p>
</div>

</div>
<div class="navfooter">
<span class="prev">
<a href="_dealing_with_null_values.html">« Dealing with Null Values</a>
</span>
<span class="next">
<a href="full-text-search.html">Full-Text Search »</a>
</span>
</div>
</div>

                  <!-- end body -->
                </div>
                <div class="col-xs-12 col-sm-4 col-md-4" id="right_col">
                  <div id="rtpcontainer" style="display: block;">
                    <div class="mktg-promo">
                      <h3>Most Popular</h3>
                      <ul class="icons">
                        <li class="icon-elasticsearch-white"><a href="https://www.elastic.co/webinars/getting-started-elasticsearch?baymax=default&amp;elektra=docs&amp;storm=top-video">Get Started with Elasticsearch: Video</a></li>
                        <li class="icon-kibana-white"><a href="https://www.elastic.co/webinars/getting-started-kibana?baymax=default&amp;elektra=docs&amp;storm=top-video">Intro to Kibana: Video</a></li>
                        <li class="icon-logstash-white"><a href="https://www.elastic.co/webinars/introduction-elk-stack?baymax=default&amp;elektra=docs&amp;storm=top-video">ELK for Logs &amp; Metrics: Video</a></li>
                      </ul>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </section>

        </div>


<div id="elastic-footer"></div>
<script src="https://www.elastic.co/elastic-footer.js"></script>
<!-- Footer Section end-->

      </section>
    </div>

<script src="/guide/static/jquery.js"></script>
<script type="text/javascript" src="/guide/static/docs.js"></script>
<script type="text/javascript">
  window.initial_state = {}</script>
  </body>
</html>
